#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#include "ohos_init.h"
#include "cmsis_os2.h"
#include "wifi_device.h"
#include "lwip/netifapi.h"
#include "lwip/api_shell.h"
#include "wifiiot_watchdog.h"

#include "device_app.h"
#include "oled.h"
#include "uart.h"
#include "led.h"
#include "buzzer.h"

#include "connect_wifi.h"
#include "tcp_client.h"
#include "aht20.h"

#include "terminal_send_task.h"
#include "ble_receive_task.h"
#include "ble_send_task.h"

device_data_t device_data;
terminal_send_data_t terminal_send_data;

extern connect_wifi_data_t connect_wifi_data;
extern server_data_t server_data;

extern ble_receive_data_t ble_receive_data;
extern ble_send_data_t ble_send_data;


static char receive_buff[128];

void hardware_init(void);
void stime_deal(void);
void faction_s(char *information);
void faction_c(char *information);
void faction_c_power_off(char *information);
void faction_c_power_on(char *information);
void faction_c_5(char *information);

void faction_c_timing_off(char *information);
void faction_c_timing_on(char *information);
void faction_c_time_off(char *information);
void faction_c_time_on(char *information);


static void terminal_send_slave_num(void);
static void terminal_send_power_off_result(void);
static void terminal_send_power_on_result(void);
static void terminal_send_relay_result(void);
static void terminal_send_timing_off_result(void);
static void terminal_send_timing_on_result(void);
static void terminal_send_time_off_result(void);
static void terminal_send_time_on_result(void);


void device_app(void* arg)
{
    (void) arg;
    int connect_time = 0;
    int connect_times = 0;
    hardware_init();
    WatchDogKick();
    while(1)
    {
        if(connect_wifi_data.wifi_connect_state == 1)     //wifi连接成功
        {
            if(server_data.server_connect_state == 1)    //服务器连接成功
            {
                recv(server_data.sockfd, &receive_buff, sizeof(receive_buff), 0);
                printf("%s\r\n", receive_buff);
                switch(receive_buff[0])
                {
                    case 't' : stime_deal(); break;
                    case 's' : faction_s(receive_buff); break;    //处理服务器发送的信息
                    case 'c' : faction_c(receive_buff); break;//处理客户端发送的消息
                    default : break;
                }
                bzero(receive_buff, strlen(receive_buff));
            }
            else if(server_data.server_connect_state == 0)
            {
                if(device_data.server_connect_flag == 1)
                {
                    connect_time++;
                    if(connect_time%60 == 0)
                    {
                        connect_time = 0;     //一分钟尝试连接一次服务器
                        connect_to_tcp_server(PARAM_SERVER_ADDR, PARAM_SERVER_PORT);
                        if(connect_times >= 11)    //连接10次失败，就不再自动连接。
                        {
                            connect_times = 0;
                            device_data.server_connect_flag = 0;
                        }
                    }
                    else if(device_data.server_connect_immediate == 1)    //马上连接服务器
                    {
                        device_data.server_connect_immediate = 0;
                        connect_to_tcp_server(PARAM_SERVER_ADDR, PARAM_SERVER_PORT);
                    }
                }               
            }
            if(device_data.wifi_connect_flag == 0)
            {
                uint8_t disconnect[18] = {"wifi disconnected"};
                disconnect_With_wifi();
                OLED_Clear_Line(1); OLED_Show_String(0, 1, 8, disconnect);
                osDelay(50); //0.5s
            }
        }
        else if(connect_wifi_data.wifi_connect_state == 0)//wifi连接失败，如果wifi_connect_flag = 1，就会自动连接
        {
            if(device_data.wifi_connect_flag == 1)
            {
                connect_time++;
                if(connect_time%60 == 0)
                {
                    connect_time = 0;     //一分钟尝试连接一次wifi
                    //connect_to_wifi();
                    connect_times++;
                    if(connect_times >= 11)    //连接10次失败，就不再自动连接。
                    {
                        connect_times = 0;
                        device_data.wifi_connect_flag = 0;
                    }
                }
                else if(device_data.wifi_connect_immediate == 1)    //立即连接wifi
                {
                    device_data.wifi_connect_immediate = 0;
                    connect_to_wifi();
                }
            }           
        }
        WatchDogKick();
        osDelay(50); //1s
    }
}

/******************************************************************************************************************************************
 *                                                         发送数据到服务器
 * ****************************************************************************************************************************************/
void send_task(void* arg)
{
    (void) arg;
    while(1)
    {
        if(connect_wifi_data.wifi_connect_state == 1)     //wifi连接成功
        {
            if(server_data.server_connect_state == 1)    //服务器连接成功
            {
                if(device_data.get_time_falg == 10)
                {
                    device_data.get_time_falg = 0;
                    send(server_data.sockfd, "t", 2, 0);    //获取时间消息
                }
                else
                {
                    device_data.get_time_falg++;
                }

                if(terminal_send_data.send_power_off_result_flag != 0 && terminal_send_data.send_power_off_result_flag != 1)
                {
                    terminal_send_power_off_result();
                }

                if(terminal_send_data.send_power_on_result_flag != 0 && terminal_send_data.send_power_on_result_flag != 1)
                {
                    terminal_send_power_on_result();
                }

                if(terminal_send_data.send_relay_state_flag == 1)    //反馈继电器状态
                {
                    terminal_send_relay_result();
                }

                if(terminal_send_data.send_timing_off_result_flag != 0 && terminal_send_data.send_timing_off_result_flag != 1)
                {
                    terminal_send_timing_off_result();
                }

                if(terminal_send_data.send_timing_on_result_flag != 0 && terminal_send_data.send_timing_on_result_flag != 1)
                {
                    terminal_send_timing_on_result();
                }

                if(terminal_send_data.send_time_off_result_flag != 0 && terminal_send_data.send_time_off_result_flag != 1)
                {
                    terminal_send_time_off_result();
                }

                if(terminal_send_data.send_time_on_result_flag != 0 && terminal_send_data.send_time_on_result_flag != 1)
                {
                    terminal_send_time_on_result();
                }
            }
            if(device_data.server_connect_flag == 0)
            {
                uint8_t disconnect[17] = {"tcp disconnected"};
                clear(server_data.sockfd);
                OLED_Clear_Line(1); OLED_Show_String(0, 1, 8, disconnect);
                osDelay(50); //0.5s
            }
        }
        WatchDogKick();
        osDelay(100); //1s
    }
}

void device_app_creat(void)
{
    osThreadAttr_t attr;

    attr.name       = "device_app";
    attr.attr_bits  = 0U;
    attr.cb_mem     = NULL;
    attr.cb_size    = 0U;
    attr.stack_mem  = NULL;
    attr.stack_size = 10240;
    attr.priority   = osPriorityNormal;

    if (osThreadNew(device_app, NULL, &attr) == NULL)
    {
        printf("[server_app_creat] Falied to create device_app!\n");
    }
}


void send_task_creat(void)
{
    osThreadAttr_t attr;

    attr.name       = "send_task";
    attr.attr_bits  = 0U;
    attr.cb_mem     = NULL;
    attr.cb_size    = 0U;
    attr.stack_mem  = NULL;
    attr.stack_size = 10240;
    attr.priority   = osPriorityNormal1;

    if (osThreadNew(send_task, NULL, &attr) == NULL)
    {
        printf("[send_task_creat] Falied to create send_task!\n");
    }
}

APP_FEATURE_INIT(device_app_creat);
APP_FEATURE_INIT(send_task_creat);

void hardware_init(void)
{
    osDelay(10); //0.1s
    oled_init();
    OLED_Clear_All();
    uart2_init();             //串口2初始化，用于蓝牙模块
    led_init();
    device_data.oled_init_state = 1;
    buzzer_init();
    device_data.aht20_init_state = AHT20_Calibrate();
    if(device_data.aht20_init_state == 0)
    {
        device_data.aht20_init_state = 1;
    }
    led_on();
    device_data.wifi_connect_flag = 1;
    device_data.wifi_connect_immediate = 1;
    device_data.server_connect_flag = 1;
    osDelay(10);
}

/******************************************************************************************************************************************
 *                                                         服务器数据处理
 * ****************************************************************************************************************************************/
void stime_deal(void)
{
    strcpy(device_data.stime, receive_buff+1);
    strcat(device_data.stime, "\0");
    device_data.get_time_falg = 1; 
}

void faction_s(char *information)
{
    uint8_t connect[] = {"server connected."};
    switch(information[1])
    {
        case 'd' : OLED_Clear_Line(1); OLED_Show_String(0, 1, 8, connect); break;    //服务器对设备登录的应答
        default : break;
    }
}

void faction_c(char *information)
{
    switch(information[1])
    {
        case '0' : break;    //
        case '1' : terminal_send_slave_num(); break;    //获取控制端号
        case '2' : faction_c_power_off(information); break;    //关电源命令
        case '3' : faction_c_power_on(information); break;    //开电源命令
        case '4' : terminal_send_data.send_relay_state_flag = 1; break;    //获取继电器状态
        case '5' : faction_c_5(information); break;    //获取总功率
        case '6' : faction_c_timing_off(information); break;    //计时关
        case '7' : faction_c_timing_on(information); break;    //计时开
        case '8' : faction_c_time_off(information); break;    //定时关
        case '9' : faction_c_time_on(information); break;    //定时开
        default : break;
    }
}

void faction_c_power_off(char *information)
{
    uint8_t slave_num = 0;
    switch(information[2])
    {
        case '0': slave_num = 0; break;
        case '1': slave_num = 1; break;
        case '2': slave_num = 2; break;
        default : break;
    }
    ble_send_data.slave_id[0] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[0];
    ble_send_data.slave_id[1] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[1];
    ble_send_data.ble_send_cmd_num = BLE_SEND_POWER_OFF;
    terminal_send_data.send_slave_num = slave_num;
    terminal_send_data.send_power_off_result_flag = 1;  //命令结果是否反馈到客服端的标志
}

void faction_c_power_on(char *information)
{
    uint8_t slave_num = 0;
    switch(information[2])
    {
        case '0': slave_num = 0; break;
        case '1': slave_num = 1; break;
        case '2': slave_num = 2; break;
        default : break;
    }
    ble_send_data.slave_id[0] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[0];
    ble_send_data.slave_id[1] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[1];
    ble_send_data.ble_send_cmd_num = BLE_SEND_POWER_ON;
    terminal_send_data.send_slave_num = slave_num;
    terminal_send_data.send_power_on_result_flag = 1;  //命令结果是否反馈到客服端的标志
}

void faction_c_5(char *information)
{
    uint8_t slave_num = 0;
    switch(information[3])
    {
        case '0': slave_num = 0; break;
        case '1': slave_num = 1; break;
        case '2': slave_num = 2; break;
        default : break;
    }
    ble_send_data.slave_id[0] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[0];
    ble_send_data.slave_id[1] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[1];
    ble_send_data.ble_send_cmd_num = BLE_SEND_GET_POWER;
}

void faction_c_timing_off(char *information)
{
    uint8_t slave_num = 0;
    switch(information[2])
    {
        case '0': slave_num = 0; break;
        case '1': slave_num = 1; break;
        case '2': slave_num = 2; break;
        default : break;
    }
    ble_send_data.slave_id[0] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[0];
    ble_send_data.slave_id[1] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[1];
    strcpy((char *)ble_send_data.ble_timing_data , information+3);
    ble_send_data.ble_send_cmd_num = BLE_SEND_TIMING_OFF;
    terminal_send_data.send_slave_num = slave_num;
    terminal_send_data.send_timing_off_result_flag = 1;  //命令结果是否反馈到客服端的标志
}

void faction_c_timing_on(char *information)
{
    uint8_t slave_num = 0;
    switch(information[2])
    {
        case '0': slave_num = 0; break;
        case '1': slave_num = 1; break;
        case '2': slave_num = 2; break;
        default : break;
    }
    ble_send_data.slave_id[0] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[0];
    ble_send_data.slave_id[1] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[1];
    strcpy((char *)ble_send_data.ble_timing_data , information+3);
    ble_send_data.ble_send_cmd_num = BLE_SEND_TIMING_ON;
    terminal_send_data.send_slave_num = slave_num;
    terminal_send_data.send_timing_on_result_flag = 1;  //命令结果是否反馈到客服端的标志
}

void faction_c_time_off(char *information)
{
    uint8_t slave_num = 0;
    switch(information[2])
    {
        case '0': slave_num = 0; break;
        case '1': slave_num = 1; break;
        case '2': slave_num = 2; break;
        default : break;
    }
    ble_send_data.slave_id[0] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[0];
    ble_send_data.slave_id[1] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[1];
    strcpy((char *)ble_send_data.ble_time_data , information+3);
    ble_send_data.ble_send_cmd_num = BLE_SEND_TIME_OFF;
    terminal_send_data.send_slave_num = slave_num;
    terminal_send_data.send_time_off_result_flag = 1;  //命令结果是否反馈到客服端的标志
}

void faction_c_time_on(char *information)
{
    uint8_t slave_num = 0;
    switch(information[2])
    {
        case '0': slave_num = 0; break;
        case '1': slave_num = 1; break;
        case '2': slave_num = 2; break;
        default : break;
    }
    ble_send_data.slave_id[0] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[0];
    ble_send_data.slave_id[1] = ble_receive_data.ble_slave_id_data[slave_num].ble_slave_id[1];
    strcpy((char *)ble_send_data.ble_time_data , information+3);
    ble_send_data.ble_send_cmd_num = BLE_SEND_TIME_ON;
    terminal_send_data.send_slave_num = slave_num;
    terminal_send_data.send_time_on_result_flag = 1;  //命令结果是否反馈到客服端的标志
}

/******************************************************************************************************************************************
 *                                                         发送数据到服务器
 * ****************************************************************************************************************************************/
static void terminal_send_slave_num(void) //只发送正常来连接的控制端号，如果有连接异常的控制端，就更新一下现在连接正常的控制端号。
{
    char send_slave_num[10] = {"d1"};
    ssize_t ssize;
    uint8_t i = 0;
    for(i=0; i<ble_receive_data.ble_num; i++)//将正常连接的设备更新到服务器
    {
        if(ble_receive_data.ble_slave_id_data[i].ble_slave_state == ON_LINE)
        {
            switch(i)
            {
                case 0 : strcat(send_slave_num, "0"); break;
                case 1 : strcat(send_slave_num, "1"); break;
                case 2 : strcat(send_slave_num, "2"); break;
                default : break;
            }
        }
    }
    ssize = send(server_data.sockfd, send_slave_num, strlen(send_slave_num), 0);    //发送正常连接控制端号
    if(ssize == -1)
    {
        server_data.server_connect_state = 0;    //发送失败马上改变连接服务器的状态
    }
    printf("send: %s\r\n", send_slave_num);
}

static void terminal_send_power_off_result(void)
{
    char send_flag = 0;
    char send_power_off_result[5] = {"d2"};
    switch (terminal_send_data.send_slave_num)
    {
        case 0 :strcat(send_power_off_result, "0"); break;
        case 1 :strcat(send_power_off_result, "1"); break;
        case 2 :strcat(send_power_off_result, "2"); break;
        default: break;
    }
    switch(terminal_send_data.send_power_off_result_flag)
    {
        case 1 : break;
        case 2 : strcat(send_power_off_result, "0"); send_flag = 1; break; //添加结果//成功                    
        case 3 : strcat(send_power_off_result, "1"); send_flag = 1; break; //添加结果//失败
        case 4 : strcat(send_power_off_result, "2"); send_flag = 1; break; //添加结果//超时
        default : break;
    }
    if(send_flag == 1)
    {
        send(server_data.sockfd, send_power_off_result, strlen(send_power_off_result), 0);
        terminal_send_data.send_power_off_result_flag = 0;
    }
}

static void terminal_send_power_on_result(void)
{
    char send_flag = 0;
    char send_power_on_result[5] = {"d3"};
    switch (terminal_send_data.send_slave_num)
    {
    case 0 :strcat(send_power_on_result, "0"); break;
    case 1 :strcat(send_power_on_result, "1"); break;
    case 2 :strcat(send_power_on_result, "2"); break;
    default: break;
    }
    switch(terminal_send_data.send_power_on_result_flag)
    {
        case 2 : strcat(send_power_on_result, "0"); send_flag = 1; break; //添加结果                    
        case 3 : strcat(send_power_on_result, "1"); send_flag = 1; break; //添加结果//失败
        case 4 : strcat(send_power_on_result, "2"); send_flag = 1; break; //添加结果//超时
        default : break;
    }
    if(send_flag == 1)
    {
        send(server_data.sockfd, send_power_on_result, strlen(send_power_on_result), 0);
        terminal_send_data.send_power_on_result_flag = 0;
    }
}


static void terminal_send_relay_result(void)
{
    char send_flag = 0;
    char send_relay_result[5] = {"d4"};
    switch (terminal_send_data.send_slave_num)
    {
    case 0 :strcat(send_relay_result, "0"); break;
    case 1 :strcat(send_relay_result, "1"); break;
    case 2 :strcat(send_relay_result, "2"); break;
    default: break;
    }
    if(ble_receive_data.ble_slave_id_data[terminal_send_data.send_slave_num].ble_slave_relay_state == 0)
    {
        strcat(send_relay_result, "0"); send_flag = 1;
    }
    else
    {
        strcat(send_relay_result, "1"); send_flag = 1;
    }
    if(send_flag == 1)
    {
        send(server_data.sockfd, send_relay_result, strlen(send_relay_result), 0);
        terminal_send_data.send_relay_state_flag = 0;
    }
}


static void terminal_send_timing_off_result(void)
{
    char send_flag = 0;
    char send_timing_off_result[5] = {"d6"};
    switch (terminal_send_data.send_slave_num)
    {
        case 0 : strcat(send_timing_off_result, "0"); break;
        case 1 : strcat(send_timing_off_result, "1"); break;
        case 2 : strcat(send_timing_off_result, "2"); break;
        default: break;
    }
    switch(terminal_send_data.send_timing_off_result_flag)
    {
        case 1 : break;
        case 2 : strcat(send_timing_off_result, "0"); send_flag = 1; break; //添加结果//成功                    
        case 3 : strcat(send_timing_off_result, "1"); send_flag = 1; break; //添加结果//失败
        case 4 : strcat(send_timing_off_result, "2"); send_flag = 1; break; //添加结果//超时
        default : break;
    }
    if(send_flag == 1)
    {
        send(server_data.sockfd, send_timing_off_result, strlen(send_timing_off_result), 0);
        terminal_send_data.send_timing_off_result_flag = 0;
    }
}

static void terminal_send_timing_on_result(void)
{
    char send_flag = 0;
    char send_timing_on_result[5] = {"d7"};
    switch (terminal_send_data.send_slave_num)
    {
        case 0  : strcat(send_timing_on_result, "0"); break;
        case 1  : strcat(send_timing_on_result, "1"); break;
        case 2  : strcat(send_timing_on_result, "2"); break;
        default : break;
    }
    switch(terminal_send_data.send_timing_on_result_flag)
    {
        case 1 : break;
        case 2 : strcat(send_timing_on_result, "0"); send_flag = 1; break; //添加结果//成功                    
        case 3 : strcat(send_timing_on_result, "1"); send_flag = 1; break; //添加结果//失败
        case 4 : strcat(send_timing_on_result, "2"); send_flag = 1; break; //添加结果//超时
        default : break;
    }
    if(send_flag == 1)
    {
        send(server_data.sockfd, send_timing_on_result, strlen(send_timing_on_result), 0);
        terminal_send_data.send_timing_on_result_flag = 0;
    }
}

static void terminal_send_time_off_result(void)
{
    char send_flag = 0;
    char send_time_off_result[5] = {"d8"};
    switch (terminal_send_data.send_slave_num)
    {
        case 0  : strcat(send_time_off_result, "0"); break;
        case 1  : strcat(send_time_off_result, "1"); break;
        case 2  : strcat(send_time_off_result, "2"); break;
        default : break;
    }
    switch(terminal_send_data.send_time_off_result_flag)
    {
        case 1  : break;
        case 2  : strcat(send_time_off_result, "0"); send_flag = 1; break; //添加结果//成功                    
        case 3  : strcat(send_time_off_result, "1"); send_flag = 1; break; //添加结果//失败
        case 4  : strcat(send_time_off_result, "2"); send_flag = 1; break; //添加结果//超时
        default : break;
    }
    if(send_flag == 1)
    {
        send(server_data.sockfd, send_time_off_result, strlen(send_time_off_result), 0);
        terminal_send_data.send_time_off_result_flag = 0;
    }
}

static void terminal_send_time_on_result(void)
{
    char send_flag = 0;
    char send_time_on_result[5] = {"d9"};
    switch (terminal_send_data.send_slave_num)
    {
        case 0  : strcat(send_time_on_result, "0"); break;
        case 1  : strcat(send_time_on_result, "1"); break;
        case 2  : strcat(send_time_on_result, "2"); break;
        default : break;
    }
    switch(terminal_send_data.send_time_on_result_flag)
    {
        case 1 : break;
        case 2 : strcat(send_time_on_result, "0"); send_flag = 1; break; //添加结果//成功                    
        case 3 : strcat(send_time_on_result, "1"); send_flag = 1; break; //添加结果//失败
        case 4 : strcat(send_time_on_result, "2"); send_flag = 1; break; //添加结果//超时
        default : break;
    }
    if(send_flag == 1)
    {
        send(server_data.sockfd, send_time_on_result, strlen(send_time_on_result), 0);
        terminal_send_data.send_time_on_result_flag = 0;
    }
}

